﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Drawing.Imaging;
namespace ExifUtils
{
    public class Exif
    {
        public static bool IsGps { get; internal set; }
        //
        public static double Latitude { get; internal set; }
        public static double Longitude { get; internal set; }
        //
        public static string Location { get { return string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0},{1}", Latitude, Longitude); } }
        //
        public static bool IsRotation { get; internal set; }
        public static int Rotation { get; internal set; }
        //
        public static string DayOfShot { get; internal set; }
        //
        public static bool GetExifData(string fileName)
        {
            Latitude = Longitude = 0.0;
            var exData = GetExifDictionary(fileName);
            if (null == exData) return false;
            //
            if (exData.ContainsKey(1) && exData.ContainsKey(2) && exData.ContainsKey(3) && exData.ContainsKey(4))
            {
                IsGps = true;
                Latitude = Tude2Double(exData[1].Value, exData[2].Value);
                Longitude = Tude2Double(exData[3].Value, exData[4].Value);
            }
            //
            //
            Rotation = 0;
            if (exData.ContainsKey(0x112))
            {
                IsRotation = true;
                //
                int orientation = exData[0x112].Value[0];
                Rotation = GetRotation(exData[0x112].Value[0]);
            }
            //
            //
            DayOfShot = "";
            if (exData.ContainsKey(0x9003))
            {
                //"2013:06:16 13:50:31\0"
                if (exData[0x9003].Value.Length > 2)
                {
                    string odt = System.Text.Encoding.UTF8.GetString(exData[0x9003].Value, 0, exData[0x9003].Value.Length - 1);
                    odt = odt.Split(new char[] { ' ' }, 2)[0];
                    DayOfShot = odt.Replace(':', '-');
                }
            }
            //
            //
            return true;
        }

        //======================================================================================================

        public static Dictionary<int, PropertyItem> GetExifDictionary(string fileName)
        {
            Dictionary<int, PropertyItem> pd = null;
            //
            using (Image img = new Bitmap(fileName))
            {
                //
                try
                {
                    pd = (from pp in img.PropertyItems orderby pp.Id select pp).ToDictionary(x => x.Id, x => x);
                }
                catch
                {
                    ;
                }
                //return (from pp in img.PropertyItems orderby pp.Id select pp).ToDictionary(x => x.Id, x => x);
            }
            //return (from pp in img.PropertyItems where pp.Id <= 30 select pp).ToList<PropertyItem>();
            return pd;
        }
        //orientation
        // 1 - OK
        // 8 - counter -90
        // 3 - -180
        // 6  - +90
        public static int GetRotation(byte tagValue)
        {
            switch (tagValue)
            {
                case 5://*
                case 6:
                    //+90
                    return 90;
                case 7://*
                case 8:
                    //-90
                    return -90;
                case 4://*
                case 3:
                    //180
                    return 180;
            }
            return 0;
        }

        private static double Tude2Double(byte[] propTudeRefValue, byte[] propTudeValue)
        {
            double tude = 0.0;

            if (2 != propTudeRefValue.Length || 24 != propTudeValue.Length)
            {
                return 0.0;
            }

            //UInt32 idegrees = BitConverter.ToUInt32(propTudeValue, 0) / BitConverter.ToUInt32(propTudeValue, 4);
            //UInt32 iminutes = BitConverter.ToUInt32(propTudeValue, 8) / BitConverter.ToUInt32(propTudeValue, 12);
            //UInt32 iseconds = BitConverter.ToUInt32(propTudeValue, 16);// / BitConverter.ToUInt32(propTudeValue, 20);

            double degrees = (double)BitConverter.ToUInt32(propTudeValue, 0) / (double)BitConverter.ToUInt32(propTudeValue, 4);
            double minutes = (double)BitConverter.ToUInt32(propTudeValue, 8) / (double)BitConverter.ToUInt32(propTudeValue, 12);
            double seconds = (double)BitConverter.ToUInt32(propTudeValue, 16) / (double)BitConverter.ToUInt32(propTudeValue, 20);
            //
            //
            tude = degrees + (minutes / 60.0) + (seconds / 3600.0);
            // S:83,115 W:87,119
            if (83 == propTudeRefValue[0] || 115 == propTudeRefValue[0] || 87 == propTudeRefValue[0] || 119 == propTudeRefValue[0]) tude = 0.0 - tude;
            //float coorditate = degrees + (minutes / 60f) + (seconds / 3600f);
            //string gpsRef = System.Text.Encoding.ASCII.GetString(new byte[1] { propItemRef.Value[0] }); //N, S, E, or W
            //if (gpsRef == "S" || gpsRef == "W")coorditate = 0 - coorditate;


            return tude;
        }

        //======================================================================================================
    }//class
}//namespace
